﻿Imports System.Drawing
Imports System.Windows.Forms
Imports System.Text.RegularExpressions
Public Class HighlightRule
    Public Sub New()
        Me.New("")
    End Sub
    Public Sub New(pattern As String)
        Me.New(pattern, SystemColors.WindowText)
    End Sub
    Public Sub New(pattern As String, color As Color)
        Me.New(pattern, color, SystemColors.Window)
    End Sub
    Public Sub New(pattern As String, color As Color, backColor As Color)
        Me.Pattern = pattern
        Me.Color = color
        Me.BackColor = backColor
    End Sub

    Public Property Pattern As String
    Public Property Color As Color
    Public Property BackColor As Color
End Class

Public Class HighlightGroup
    Public Sub New()
        Me.Extensions = New List(Of String)
        Me.Rules = New List(Of HighlightRule)
    End Sub
    Public Sub New(name As String)
        Me.New()
        Me.Name = name
    End Sub
    Public Sub New(name As String, extensions As String)
        Me.New(name, {extensions}.ToList, Nothing)
    End Sub
    Public Sub New(name As String, extensions As String(), rules As HighlightRule())
        Me.New(name, extensions.ToList, rules.ToList)
    End Sub
    Public Sub New(name As String, extensions As String(), rules As List(Of HighlightRule))
        Me.New(name, extensions.ToList, rules)
    End Sub
    Public Sub New(name As String, extensions As List(Of String), rules As List(Of HighlightRule))
        Me.Name = name
        Me.Extensions = If(extensions, New List(Of String))
        Me.Rules = If(rules, New List(Of HighlightRule))
    End Sub

    Public Property Name As String
    Public Property Extensions As List(Of String)
    Public Property Rules As List(Of HighlightRule)

    Public Shared Function GetHighlightRules(list As List(Of HighlightGroup), extension As String, Optional includeTypeAll As Boolean = True)
        Return GetHighlightRules(list, {extension}, includeTypeAll)
    End Function
    Public Shared Function GetHighlightRules(list As List(Of HighlightGroup), extensions As String(), Optional includeTypeAll As Boolean = True)
        Return GetHighlightRules(list, extensions.ToList, includeTypeAll)
    End Function
    Public Shared Function GetHighlightRules(list As List(Of HighlightGroup), extensions As List(Of String), Optional includeTypeAll As Boolean = True)
        extensions = If(extensions, New List(Of String))
        If includeTypeAll AndAlso Not extensions.Contains(".*") Then extensions.Add(".*")

        Dim rules As New List(Of HighlightRule)
        list.ForEach(Sub(item) If item.Extensions.Exists(Function(subitem) extensions.Exists(Function(match) Trim(match).ToLower = Trim(subitem).ToLower)) Then rules.AddRange(item.Rules))

        Return rules
    End Function
End Class

Public Class Highlight
    Private _isBusy As Boolean = False

    Public Sub New()
        Me.New(New RichTextBox, New HighlightRule)
    End Sub
    Public Sub New(richText As RichTextBox)
        Me.New(richText, New HighlightRule)
    End Sub
    Public Sub New(richText As RichTextBox, rules As HighlightRule)
        Me.New(richText, {rules}.ToList)
    End Sub
    Public Sub New(richText As RichTextBox, rules() As HighlightRule)
        Me.New(richText, rules.ToList)
    End Sub
    Public Sub New(richText As RichTextBox, rules As List(Of HighlightRule))
        Me.New(richText, rules, SystemColors.WindowText, SystemColors.Window)
    End Sub
    Public Sub New(richText As RichTextBox, rules As HighlightRule, defaultColor As Color, defaultBackColor As Color)
        Me.New(richText, {rules}.ToList, defaultColor, defaultBackColor)
    End Sub
    Public Sub New(richText As RichTextBox, rules As HighlightRule(), defaultColor As Color, defaultBackColor As Color)
        Me.New(richText, rules.ToList, defaultColor, defaultBackColor)
    End Sub
    Public Sub New(richText As RichTextBox, rules As List(Of HighlightRule), defaultColor As Color, defaultBackColor As Color)
        Me.RichText = richText
        Me.Rules = rules
        Me.DefaultColor = defaultColor
        Me.DefaultBackColor = defaultBackColor
    End Sub

    Public Sub SetDefault(richText As RichTextBox)
        With richText
            Dim index As Integer = .SelectionStart

            .SelectAll()
            .SelectionColor = Me.DefaultColor
            .SelectionBackColor = Me.DefaultBackColor

            .SelectionStart = index
            .SelectionLength = 0
        End With
    End Sub

    Public Sub Make(Optional isDefaultBefore As Boolean = False)
        Call Me.Make(Me.RichText, Me.Rules, Me.DefaultColor, Me.DefaultBackColor, isDefaultBefore)
    End Sub
    Public Sub Make(richText As RichTextBox, Optional isDefaultBefore As Boolean = False)
        Call Me.Make(richText, Me.Rules, Me.DefaultColor, Me.DefaultBackColor, isDefaultBefore)
    End Sub
    Public Sub Make(rules As HighlightRule, Optional isDefaultBefore As Boolean = False)
        Call Me.Make(Me.RichText, {rules}.ToList, Me.DefaultColor, Me.DefaultBackColor, isDefaultBefore)
    End Sub
    Public Sub Make(rules As HighlightRule, defaultColor As Color, Optional isDefaultBefore As Boolean = False)
        Call Me.Make(Me.RichText, {rules}.ToList, defaultColor, Me.DefaultBackColor, isDefaultBefore)
    End Sub
    Public Sub Make(rules As HighlightRule, defaultColor As Color, defaultBackColor As Color, Optional isDefaultBefore As Boolean = False)
        Call Me.Make(Me.RichText, {rules}.ToList, defaultColor, defaultBackColor, isDefaultBefore)
    End Sub
    Public Sub Make(rules As HighlightRule(), defaultColor As Color, defaultBackColor As Color, Optional isDefaultBefore As Boolean = False)
        Call Me.Make(Me.RichText, rules.ToList, defaultColor, Me.DefaultBackColor, isDefaultBefore)
    End Sub
    Public Sub Make(richText As RichTextBox, rules As List(Of HighlightRule), defaultColor As Color, defaultBackColor As Color, Optional isDefaultBefore As Boolean = False)
        _isBusy = True
        If isDefaultBefore Then Call Me.SetDefault(richText)
        Call Make(richText, rules, defaultColor, defaultBackColor)
        _isBusy = False
    End Sub

    Public Shared Sub Make(richText As RichTextBox, rules As HighlightRule)
        Call Make(richText, rules, SystemColors.WindowText)
    End Sub
    Public Shared Sub Make(richText As RichTextBox, rules As HighlightRule, defaultColor As Color)
        Call Make(richText, {rules}.ToList, defaultColor, SystemColors.Window)
    End Sub
    Public Shared Sub Make(richText As RichTextBox, rules As HighlightRule, defaultColor As Color, defaultBackColor As Color)
        Call Make(richText, {rules}.ToList, defaultColor, defaultBackColor)
    End Sub
    Public Shared Sub Make(richText As RichTextBox, rules As HighlightRule(), defaultColor As Color, defaultBackColor As Color)
        Call Make(richText, rules.ToList, defaultColor, defaultBackColor)
    End Sub
    Public Shared Sub Make(richText As RichTextBox, rules As List(Of HighlightRule), defaultColor As Color, defaultBackColor As Color)
        With richText
            Dim index As Integer = .SelectionStart
            Dim input As String = .Text.Replace(vbCrLf, vbLf)
            For Each item In rules
                If Trim(item.Pattern).Equals("") Then Continue For
                Dim matches As MatchCollection = Regex.Matches(input, item.Pattern)
                For Each match As Match In matches
                    .Select(match.Index, match.Value.Length)
                    .SelectionColor = item.Color
                    .SelectionBackColor = item.BackColor
                Next
            Next
            .SelectionStart = input.Length
            .SelectionLength = 0
            .SelectionColor = defaultColor
            .SelectionBackColor = defaultBackColor
            .SelectionStart = index
        End With
    End Sub

    Public Property RichText As RichTextBox
    Public Property Rules As List(Of HighlightRule)
    Public Property DefaultColor As Color
    Public Property DefaultBackColor As Color
    Public ReadOnly Property IsBusy As Boolean
        Get
            Return _isBusy
        End Get
    End Property
End Class